Skip to content

Regenerate the synchronous client with the modern Python generator#2631

Merged
kubernetes-prow[bot] merged 2 commits into
kubernetes-client:masterfrom
tamird:prototype/modern-openapi-generator
Jul 22, 2026
Merged

Regenerate the synchronous client with the modern Python generator#2631
kubernetes-prow[bot] merged 2 commits into
kubernetes-client:masterfrom
tamird:prototype/modern-openapi-generator

Conversation

@tamird

@tamird tamird commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

/kind feature

What this PR does / why we need it:

The synchronous client is still generated with OpenAPI Generator 6.6's
python-legacy backend. OpenAPI Generator removed that backend in v7,
so the current generation path cannot move to a supported generator or
inherit the modern Python generator's native type information.

This PR moves the synchronous client to the modern python backend:

  • regenerate the client and Sphinx API index with Pydantic models and
    modern generated type information;
  • declare the generated runtime requirements and package py.typed;
  • adapt dynamic, stream, watch, OIDC, YAML, and example helpers to the
    modern generated API;
  • preserve Kubernetes IntOrString, CRD JSON-schema, and Namespace-delete
    representations under Pydantic validation;
  • preserve dict, JSON Patch, and generated-model PATCH bodies; and
  • remove obsolete post-generation hotfixes while retaining the small
    body-aware PATCH media-type correction.

The generated client has 768 models, 65 API modules, and 1,872
API-call validators. Loading all of them during import makes
short-lived callers substantially slower. Generated packages now use
the generator's built-in lazy imports, and validators are built on
first use. Measured cold import falls from 1.19s to 0.16s while public
exports, constructor signatures, first-call validation, and importlib
package metadata are preserved.

Which issue(s) this PR fixes:

No single tracked issue. The regeneration fixes existing urllib
compatibility, typing, and bytes-handling gaps in the synchronous
client.

Special notes for your reviewer:

The paired generator migration is
kubernetes-client/gen#305. It selects the
released OpenAPI Generator v7.24.0, which contains the required legacy
compatibility and API-key-prefix fixes. The generated provenance records
the release tag and resolved commit 203d4867.

This changes synchronous generation only. The async client remains on
its existing generator path and should be regenerated separately; until
then, six remains an async requirement.

The changelog documents the synchronous runtime dependency changes,
stricter model and API-call validation, removed low-level transport
interfaces, decoded exception bodies, and Namespace-delete return type.
Existing endpoint names, model names, and wire aliases are preserved.

Legacy async_req=True still returns an ApplyResult consumed with
.get(), and _preload_content=False returns the raw response.
Ordinary return annotations intentionally describe the default call:
Watch reflects them to select event models. The generator rationale is
OpenAPITools/openapi-generator#24300.

The initial release render was produced by the normal
scripts/update-client.sh Docker path in
https://github.com/tamird/kubernetes-python/actions/runs/29785873376.
Until the paired generator PR merges, reproduce it with that generator
branch checked out locally:

GEN_ROOT=/path/to/kubernetes-client-gen scripts/update-client.sh

The previous head passed the fork's Python 3.10-3.14 lint and test
matrix, but the upstream E2E run exposed valid IntOrString values and
Namespace-delete responses rejected by the generated validators, along
with invalid scalar exec arguments and lowercase resourceversion
fixtures. The replacement run exposed one remaining discovery 415: the
modern selector sent literal */* where the legacy client defaulted to
JSON. This update corrects those cases and adds focused regressions.

The current upstream Python 3.10-3.14 validation and Python 3.10-3.12
E2E matrices are waiting for maintainer approval:
https://github.com/kubernetes-client/python/actions/runs/29936539412
https://github.com/kubernetes-client/python/actions/runs/29936538730
The matching exact-head fork Python 3.10-3.14 validation matrix passes:
https://github.com/tamird/kubernetes-python/actions/runs/29936531993.

Does this PR introduce a user-facing change?

The synchronous Python client is regenerated with the modern OpenAPI
Generator Python backend. See CHANGELOG for backward-incompatible
changes.

Additional documentation:


@kubernetes-prow kubernetes-prow Bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. release-note Denotes a PR that will be considered when it comes time to generate release notes. kind/feature Categorizes issue or PR as related to a new feature. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Jul 14, 2026
@kubernetes-prow
kubernetes-prow Bot requested review from fabianvf and roycaihw July 14, 2026 00:51
@kubernetes-prow kubernetes-prow Bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Jul 14, 2026
@penguinolog

penguinolog commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Which issue(s) this PR fixes:

technically ton of (urllib compatibility, typing, several broken places with bytes processing)

Comment thread requirements.txt Outdated
@tamird

tamird commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Right; this is not tied to one tracked issue. I updated that section to name the urllib compatibility, typing, and bytes-handling gaps instead of saying None.

Comment thread kubernetes/.openapi-generator/VERSION Outdated
@tamird
tamird force-pushed the prototype/modern-openapi-generator branch from 77e286b to 6bc343e Compare July 15, 2026 23:26
@roycaihw

Copy link
Copy Markdown
Member

/assign @yliaog

@kubernetes-prow kubernetes-prow Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 16, 2026
@tamird
tamird force-pushed the prototype/modern-openapi-generator branch from 6bc343e to c248094 Compare July 16, 2026 23:48
@kubernetes-prow kubernetes-prow Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 17, 2026
@tamird
tamird marked this pull request as ready for review July 21, 2026 00:14
@kubernetes-prow kubernetes-prow Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 21, 2026
@tamird
tamird force-pushed the prototype/modern-openapi-generator branch from 2edde6c to af93dd7 Compare July 21, 2026 00:29
@tamird
tamird force-pushed the prototype/modern-openapi-generator branch from af93dd7 to 325ae7c Compare July 21, 2026 16:57
@yliaog

yliaog commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

@tamird thanks for the PR, do you know whether the import latency issue reported in tomplus/kubernetes_asyncio#293 is resolved with the new openapi generator?

@yliaog

yliaog commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

could you also please take a look at the failure tests? https://github.com/kubernetes-client/python/actions/runs/29850863235/job/88758260386?pr=2631

@tamird
tamird force-pushed the prototype/modern-openapi-generator branch from 325ae7c to 5353a3d Compare July 21, 2026 22:36
@tamird

tamird commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

@yliaog Both are addressed in 5353a3d, with the paired generator update in kubernetes-client/gen#305.

The E2E failures were real. The modern client was validating Kubernetes IntOrString fields as dictionaries and Namespace DELETE responses as Status, so valid rolling-update percentages, service/probe ports, and terminating Namespaces failed. I also corrected the scalar exec arguments and invalid lowercase resourceversion fixtures. The remaining conflicts and UnboundLocalError failures were cascades. Focused regressions now cover those cases and pass locally.

Import latency is improved, though not eliminated. On the same Python 3.12 setup, the published legacy client imports in about 0.2s and the v7.24 render took about 3s. Deferring the 1,872 Pydantic call validators (supported since Pydantic 2.11, which this client already requires) reduces the render to about 1.1s while retaining first-call argument validation.

The replacement upstream E2E run is waiting for approval:
https://github.com/kubernetes-client/python/actions/runs/29874378845

Could you approve that run? The exact-head fork validation matrix is also running:
https://github.com/tamird/kubernetes-python/actions/runs/29874376044

@tamird
tamird force-pushed the prototype/modern-openapi-generator branch from 5353a3d to 1181255 Compare July 22, 2026 00:01
@tamird

tamird commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

@yliaog The replacement E2E run reduced the failures to one discovery-time 415. The modern selector sent a literal Content-Type: */* for DynamicClient discovery GETs; the legacy selector translated that to application/json, which those routes require. This is fixed in 1181255, with a request-level regression. The apply PATCH itself remains application/apply-patch+yaml with the correct body and field manager.

Could you approve the new E2E run?
https://github.com/kubernetes-client/python/actions/runs/29878983770

@yliaog

yliaog commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

are their breaking / backward incompatible changes we should document in CHANGELOG?

@yliaog

yliaog commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

@tamird it seems that the import latency is still very big, 19s vs 0.8s, could you please take a look?

$ git checkout pr-2631
$ time PYTHONPATH=. python -c "import kubernetes; print(kubernetes.file)"
real 0m19.764s
user 0m18.475s
sys 0m1.302s

$ git checkout master
$ time PYTHONPATH=. python -c "import kubernetes; print(kubernetes.file)"
real 0m0.816s
user 0m0.559s
sys 0m0.280s

Comment thread scripts/apply-hotfixes.sh
exit 1
fi;

git commit -m "Apply hotfixes"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this file removed? i think the hotfixes are still needed after upgrading openapi generator to v7.24.0

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fixes are still present; the removed script is only the old mechanism for cherry-picking v6.6-specific commits after generation.

  • Custom-object PATCH defaults to merge patch, with explicit JSON Patch still supported and covered by request-level tests.
  • no_proxy, proxy environment variables, and proxy bypass are handled by the v7.24 generated Configuration/REST client; the existing proxy cases and a real request-level bypass test pass.
  • Bearer-token fallback remains in both synchronous and asyncio Configuration.auth_settings(); the existing regression tests pass.
  • The deprecated kubernetes.client.apis alias, API-client context-manager/thread-pool cleanup, and informer/metrics tests are all retained.

The old script would reapply commits against the previous generator layout, while these behaviors are now either generated directly or already checked in. The API-client, informer, and metrics suites pass 55 tests, and the exact-head upstream validation and E2E runs are green.

— tamirdex

@tamird
tamird force-pushed the prototype/modern-openapi-generator branch from 581eeac to dd9ffa5 Compare July 22, 2026 16:06
OpenAPI Generator v7 removed python-legacy, preventing the synchronous
Kubernetes client from moving beyond v6.6.0 and inheriting the modern
Python generator's native type information.

Regenerate with the released v7.24.0 Python generator, declare its
runtime requirements, package py.typed, and refresh the Sphinx API
index. Adapt dynamic, stream, watch, OIDC, YAML, leader-election, and
example callers to the modern transport and legacy-compatible response
behavior.

Remove obsolete post-generation hotfixes while retaining the small REST
correction that selects strategic merge for built-in object patches and
JSON Patch for operation lists. Preserve dict, JSON Patch, and generated
model PATCH bodies, Kubernetes IntOrString and CRD JSON-schema
representations, and both successful Namespace-delete response shapes.

Load generated APIs and models on first use, reducing cold import from
about 1.2 seconds to 0.16 seconds while preserving public imports,
constructor signatures, importlib metadata, and first-call validation.
Defer the remaining Pydantic call validators and restore DynamicClient's
JSON discovery default to avoid wildcard Content-Type on discovery.
Correct invalid exec and metadata test inputs, cover these behaviors and
asynchronous YAML creation with request-level compatibility tests, and
document the remaining synchronous breaking changes in the changelog.
@tamird
tamird force-pushed the prototype/modern-openapi-generator branch from dd9ffa5 to bfe130d Compare July 22, 2026 16:06
@tamird

tamird commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

@yliaog Fixed in bfe130d, with the paired generator update in kubernetes-client/gen#305.

The generated client, API, and model packages now use OpenAPI Generator's built-in lazy imports instead of eagerly loading 768 models and 65 API modules. Pydantic call validators still build on first use, and package metadata remains available to importlib.

On the same Python 3.12 setup, cold import kubernetes now takes 0.16–0.19s, down from 1.19s on the previous PR head. Public imports, constructor signatures, recursive models, and first-call validation are preserved. The focused suites pass under both Pydantic 2.11 and 2.13, and the exact-head Python 3.10–3.14 fork validation matrix passes:
https://github.com/tamird/kubernetes-python/actions/runs/29936531993

The new upstream validation and E2E runs, and the paired generator run, need maintainer approval:
https://github.com/kubernetes-client/python/actions/runs/29936539412
https://github.com/kubernetes-client/python/actions/runs/29936538730
https://github.com/kubernetes-client/gen/actions/runs/29936513495

— tamirdex

Comment thread scripts/release.sh
Comment thread scripts/apply-hotfixes.sh
Comment thread scripts/apply-hotfixes.sh
Comment thread scripts/apply-hotfixes.sh
Comment thread scripts/release.sh
@yliaog

yliaog commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Now the import latency is on par

$ git checkout master
$ time python -c "import kubernetes.client.api_client; print(kubernetes.client.api_client.file)"
real 0m0.615s
user 0m0.444s
sys 0m0.195s

$ git checkout pr-2631
$ time python -c "import kubernetes.client.api_client; print(kubernetes.client.api_client.file)"

real 0m0.599s
user 0m0.490s
sys 0m0.128s

@yliaog

yliaog commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

@tamird thanks for the PR, could you help with upgrading the async client too?

/lgtm
/approve

@kubernetes-prow kubernetes-prow Bot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jul 22, 2026
@kubernetes-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: tamird, yliaog

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubernetes-prow kubernetes-prow Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 22, 2026
@kubernetes-prow
kubernetes-prow Bot merged commit ed9ffd4 into kubernetes-client:master Jul 22, 2026
10 checks passed
@tamird
tamird deleted the prototype/modern-openapi-generator branch July 22, 2026 23:48
@tamird

tamird commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

@yliaog The merged change upgrades the synchronous client; the asyncio client still uses the separate v6.6.0 python-asyncio generator. 7e155ac preserves async bearer-token fallback and prefix handling through future regeneration, so the synchronous upgrade does not break asyncio. Upgrading asyncio itself to v7.24.0 is a separate generator and compatibility migration, not part of this merged PR. The paired synchronous generator update is still in kubernetes-client/gen#305.

— tamirdex

@tamird
tamird restored the prototype/modern-openapi-generator branch July 22, 2026 23:48
@tamird
tamird deleted the prototype/modern-openapi-generator branch July 22, 2026 23:49
@tamird

tamird commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

@yliaog yes I will look into upgrading the async generator!

@tamird

tamird commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

Following up on your request to upgrade the async client: the shared generator migration is kubernetes-client/gen#305, and the regenerated async client and breaking-change documentation are #2647.

— tamirdex

@yliaog

yliaog commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

thanks, i'll take a look.

@tomplus

tomplus commented Jul 23, 2026

Copy link
Copy Markdown
Member

Hi, I'm trying to understand this step

Fixed in bfe130d, with the paired generator update in kubernetes-client/gen#305.

(#2631 (comment))

As it was committed via a force-push, I can't see the diff. What change caused such a big speed improvement?

@tamird

tamird commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

Hi, I'm trying to understand this step

Fixed in bfe130d, with the paired generator update in kubernetes-client/gen#305.

(#2631 (comment))

As it was committed via a force-push, I can't see the diff. What change caused such a big speed improvement?

https://github.com/kubernetes-client/gen/pull/305/changes#diff-c793fca58c37cbba87ce8aa71cd873051b5e7d692c2f3a154b385cae8a2322d2R125-R144

@tomplus

tomplus commented Jul 23, 2026

Copy link
Copy Markdown
Member

Thanks for the clarification, lazy-imports does the job.

For the record, here is the ongoing discussion OpenAPITools/openapi-generator#21831

@yliaog

yliaog commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

thanks @tomplus and @tamird, this is valid concern. I think we have a few options:

1/ stick with the v6.6 OpenAPI generator
2/ Keep the v7.24 OpenAPI generator, without using lazy-imports
3/ Keep the v7.24 OpenAPI generator, and laze-imports, make it configurable, optional

What do you think?

@tamird

tamird commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

@yliaog @tomplus I think there is a fourth option. OpenAPI Generator v7.24 does not require lazy-imports; the client explicitly enables the generator’s lazyImports option. Going back to v6.6 or disabling lazy loading would forfeit the measured startup improvement, while making the dependency optional would leave generated code importing it whenever laziness is enabled.

I’m preparing and validating a generator-source change that implements lazy model and API exports with Python’s standard-library module getattr and importlib, as described in https://peps.python.org/pep-0562/. That would keep v7.24 and lazy loading, remove lazy-imports and its generated dependency metadata, and eliminate the sys.modules/module-metadata workaround while addressing the supply-chain concern in OpenAPITools/openapi-generator#21831. Once validated, I’ll update the merged synchronous client and the synchronous and asyncio generator changes from the same upstream source.

— tamirdex

@yliaog

yliaog commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

totally, the 4th option as you suggested is preferred, that addresses the supply-chain concern, and the model import latency at the same time. thanks for looking into that.

@tamird

tamird commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

@yliaog @tomplus The dependency-free fourth option is now available at OpenAPITools/openapi-generator#24402. It keeps the v7.24 generator and deferred model/API imports while replacing lazy-imports and the sys.modules workaround with Python’s standard library. Once the generator fix is accepted, I’ll regenerate the merged synchronous client and the synchronous and asyncio generator changes from the same source.

— tamirdex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/feature Categorizes issue or PR as related to a new feature. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants